package com.itlong.cloud.service.impl;

import com.itlong.cloud.POJO.DTO.smartcard.SmartCardSyncDataPullUserBasisInfoDTO;
import com.itlong.cloud.POJO.DTO.smartcard.SmartCardSyncGetPullDataDTO;
import com.itlong.cloud.POJO.PO.SmartCardPullPO;
import com.itlong.cloud.POJO.PO.TimeTaskPullRemoveRepeatPO;
import com.itlong.cloud.POJO.VO.smartcard.SmartCardPullTableInfoVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.dao.ISmartCardSyncDataPullDao;
import com.itlong.cloud.enumerate.SmartCardSyncDataStatusEnum;
import com.itlong.cloud.service.ISmartCardSyncDataPullService;
import com.itlong.cloud.service.RedisService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import java.nio.channels.Channel;
import java.util.*;

/**
 * <desc>
 *      与旺龙一卡通对接-操作一卡通pull云端的数据的接口实现类
 * </desc>
 *
 * @createDate 2017-11-01
 */
@Service
public class SmartCardSyncDataPullServiceImpl implements ISmartCardSyncDataPullService {
    private static final Logger LOG = LoggerFactory.getLogger(SmartCardSyncDataPullServiceImpl.class);

    @Autowired
    private ISmartCardSyncDataPullDao iSmartCardSyncDataPullDao;


    @Autowired
    RedisService redisService;  //Reids操作对象

    /**
     * <desc>
     *      存储项目中各处数据更改点传输过来的数据
     * <desc/>
     *
     * @param  tableName 表名
     * @param smartCardPullPOS 与旺龙一卡通对接数据存储实体对象列表
     * @return
     * @author zhangs
     * @createDate 2017/11/3
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer batchSavePullData(String tableName, List<SmartCardPullPO> smartCardPullPOS){
//        LOG.info("【与旺龙一卡通对接-存储项目中各处数据更改点传输过来的数据】info:" + JSON.toJSONString(smartCardPullPO));
        Integer result = 0;
//        String projectId = smartCardPullPO.getProjectId();
//        String data = smartCardPullPO.getSyncData();
//        Integer type = smartCardPullPO.getDataType();
//        String tableName = smartCardPullPO.getTableName();
        //参数合法性判断
//        if((StringUtils.isBlank(projectId)) || (StringUtils.isEmpty(data)) || (type == null)) {
//            return result;
//        }
//
//        if(StringUtils.isEmpty(tableName)) {
//            tableName = PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PULL + projectId;
//            smartCardPullPO.setTableName(tableName);
//        }
        //创建相关数据表
        this.beforeHandlePullTable(tableName);
        //存储修改的数据
        result = iSmartCardSyncDataPullDao.batchSavePullData(tableName,smartCardPullPOS);
        //记录数据发生改变需要去重的pull信息
        //this.recordPullTableStatus(tableName);

        return result;
    }

    /**
     * <desc>
     * 保存推送给一卡通的数据.
     * </desc>
     *
     * @param tableName       表名
     * @param smartCardPullPO 待保存的数据
     * @return 受影响的行数
     * @author LewisLouis
     * @createDate 2017-12-21
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer savePullData(String tableName, SmartCardPullPO smartCardPullPO) {
        this.beforeHandlePullTable(tableName);
        return iSmartCardSyncDataPullDao.savePullData(tableName,smartCardPullPO);
    }

    /**
     * <desc>
     * 条件查询推送给一卡通的数据
     * </desc>
     *
     * @param tableName       表名
     * @param smartCardPullPO 查询条件
     * @return 受影响的行数
     * @author LewisLouis
     * @createDate 2017-12-21
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<SmartCardPullPO> getPullData(String tableName, SmartCardPullPO smartCardPullPO) {
        this.beforeHandlePullTable(tableName);
        return iSmartCardSyncDataPullDao.getPullData(tableName,smartCardPullPO);
    }

    /**
     * <desc>
     *     更新推送给一卡通的数据.
     * </desc>
     *
     * @param tableName       表名
     * @param smartCardPullPO 待更新数据
     * @return xx
     * @author LewisLouis
     * @createDate 2017-12-21
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer updatePullData(String tableName, SmartCardPullPO smartCardPullPO) {
        this.beforeHandlePullTable(tableName);
        return iSmartCardSyncDataPullDao.updatePullData(tableName,smartCardPullPO);
    }

    /**
     * <desc>
     * 根据用户Id获取用户手机号.
     * </desc>
     *
     * @param userId 用户Id
     * @return 用户手机号
     * @author LewisLouis
     * @createDate 2017-12-21
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public String getUserPhoneByUserId(String userId) {
        return iSmartCardSyncDataPullDao.getUserPhoneByUserId(userId);
    }

    /**
     * <desc>
     * 查询App用户项目基本信息-.
     * </desc>
     *
     * @param projectId 项目Id
     * @param userId    用户Id
     * @return 查询结果集
     * @author LewisLouis
     * @createDate 2017-12-22
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<SmartCardSyncDataPullUserBasisInfoDTO> getUserBasisInfo(String projectId, String userId) {
        return iSmartCardSyncDataPullDao.getUserBasisInfo(projectId,userId);
    }

    /**
     * <desc>
     * 获取指定类型的未同步数据数据.
     * </desc>
     *
     * @param smartCardSyncGetPullDataDTO  获取推送给一卡通的数据查询条件对象
     * @return dataType
     * @author LewisLouis
     * @createDate 2017-12-25
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<SmartCardPullPO> getNotSyncData(SmartCardSyncGetPullDataDTO smartCardSyncGetPullDataDTO) {


        String tableName = String.format("%s%s", PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PULL ,smartCardSyncGetPullDataDTO.getProjectId());

        this.beforeHandlePullTable(tableName);
        //将上一次成功的同步数据根据同步序号进行状态更新（更新为已同步）
        if (StringUtils.isNotBlank(smartCardSyncGetPullDataDTO.getLastSyncSerialNos())){
            List<String> lastSyncSerailNoList = Arrays.asList(smartCardSyncGetPullDataDTO.getLastSyncSerialNos().split(","));
            if (!lastSyncSerailNoList.isEmpty()){
                iSmartCardSyncDataPullDao.batchUpdatePullDataSyncStatus(tableName,lastSyncSerailNoList);
            }
        }

        //查询表tableName中的未同步的记录信息
        SmartCardPullPO querySmartCardPullPO = new SmartCardPullPO();
        querySmartCardPullPO.setDataType(smartCardSyncGetPullDataDTO.getDataType().getType());
        querySmartCardPullPO.setSyncStatus(SmartCardSyncDataStatusEnum.NOT_SYNC.getType());
        List<SmartCardPullPO> smartCardPullPOList = iSmartCardSyncDataPullDao.getPullData(tableName,querySmartCardPullPO);
        return smartCardPullPOList;
    }


    /**
     * <desc>
     *     记录数据发生改变需要去重的pull表信息
     * <desc/>
     *
     * @param tableName pull表名
     * @return
     * @author zhangs
     * @createDate 2017/10/31
     */
//    private void recordPullTableStatus(String tableName) {
//        Map<String, Object> param = new HashMap<>();
//        param.put("tableName", tableName);
//        List<TimeTaskPullRemoveRepeatPO> timeTaskPullRemoveRepeatPOS = iSmartCardSyncDataPullDao.obtainPullTableName(param);
//        if(timeTaskPullRemoveRepeatPOS != null && !timeTaskPullRemoveRepeatPOS.isEmpty()) {
//            TimeTaskPullRemoveRepeatPO timeTaskPullRemoveRepeatPO = timeTaskPullRemoveRepeatPOS.get(0);
//            Integer mark = timeTaskPullRemoveRepeatPO.getMark();
//            if(!PlatformConstants.MARTCARD_SYNC_DATA_STATUS_YET.equals(String.valueOf(mark))) {
//                timeTaskPullRemoveRepeatPO.setMark(Integer.parseInt(PlatformConstants.MARTCARD_SYNC_DATA_STATUS_YET));
//                iSmartCardSyncDataPullDao.updatePullTableStatus(timeTaskPullRemoveRepeatPO);
//            }
//        } else {
//            TimeTaskPullRemoveRepeatPO timeTaskPullRemoveRepeatPO = new TimeTaskPullRemoveRepeatPO();
//            timeTaskPullRemoveRepeatPO.setTableName(tableName);
//            timeTaskPullRemoveRepeatPO.setMark(Integer.parseInt(PlatformConstants.MARTCARD_SYNC_DATA_STATUS_YET));
//            iSmartCardSyncDataPullDao.savePullTableName(timeTaskPullRemoveRepeatPO);
//        }
//    }

    /**
     * <desc>
     *     一卡通请求获取云端数据之后云端确认一卡通是否同步成功
     * <desc/>
     *
     * @param projectId 项目Id
     * @param syncSerialNos 同步流水号
     * @return
     * @author zhangs
     * @createDate 2017/10/31
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void confirmInfo(String projectId, String syncSerialNos) {
        if(StringUtils.isBlank(projectId) || StringUtils.isEmpty(syncSerialNos)) {
            return;
        }
        String tableName = PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PULL + projectId;
        //将上一次成功的同步数据根据同步序号进行状态更新（更新为已同步）
        if (StringUtils.isNotBlank(syncSerialNos)){
            List<String> lastSyncSerailNoList = Arrays.asList(syncSerialNos.split(","));
            //ArrayList支持remove
            lastSyncSerailNoList  =  new ArrayList<>(lastSyncSerailNoList);
            Iterator<String>   iterator =  lastSyncSerailNoList.iterator();
            //遍历流水号
            while(iterator.hasNext()){
                //流水号
                String  syncSN =   iterator.next();
                //redis键
                String  key  =  new  StringBuilder(RedisConstant.SMART_CARD_SYNC_SERIAL_NUM_REDIS_KEY)
                                    .append(projectId).append(syncSN).toString();
                //redis缓存（过期）时间
                long   expTime  = RedisConstant.SMART_CARD_SYNC_SERIAL_NUM_CACHE_TIME;
                //获取redis锁
                boolean  getLock  =  redisService.setNx(key,expTime,syncSN);
                //获取不到锁表示是其他线程过来的批量更新数据库的请求
                //相同处理的数据remove，否则不同线程批量更新数据库相同的数据，会引起死锁
                if(!getLock){
                    iterator.remove();
                }
            }
            if (!lastSyncSerailNoList.isEmpty()){
                iSmartCardSyncDataPullDao.batchUpdatePullDataSyncStatus(tableName,lastSyncSerailNoList);
            }
        }
//        //更新pull表中已同步数据的同步状态
//        Map<String, Object> params = new HashMap<>();
//        String tableName = PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PULL + projectId;
//        params.put("tableName", tableName);
//        params.put("syncSerialNo", serialNumber);
//        params.put("syncMark", SmartCardSyncDataStatusEnum.SYNC_FINSH.getType());
//        params.put("updateTime", new Date());
//        iSmartCardSyncDataPullDao.updatePullDataSyncStatus(params);
    }


    /**
     * <desc>
     *     整理Pull表中数据的定时任务获取有数据变动的pull表
     * <desc/>
     *
     * @param mark 数据变动标记 0:无变动 | 1:有变动
     * @return List<TimeTaskPullRemoveRepeatPO> 定时任务临时表数据集
     * @author zhangs
     * @createDate 2017/11/3
     */
    @Override
    public List<TimeTaskPullRemoveRepeatPO> obtainPullTableName(Integer mark) {
        if(mark == null) {
            return new ArrayList<>();
        }
        Map<String, Object> param = new HashMap<>();
        param.put("mark", mark);
        return iSmartCardSyncDataPullDao.obtainPullTableName(param);
    }

    /**
     * <desc>
     *     更新表time_task_pull_remove_repeat中pull表名对应的数据处理状态
     * <desc/>
     *
     * @param timeTaskPullRemoveRepeatPO 存储有数据变化的pull表信息的定时任务临时表
     * @return
     * @author zhangs
     * @createDate 2017/11/3
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updateTimeTaskPullStatus(@RequestParam("timeTaskPullRemoveRepeatPO") TimeTaskPullRemoveRepeatPO timeTaskPullRemoveRepeatPO) {
        String tableName = timeTaskPullRemoveRepeatPO.getTableName();
        Integer mark = timeTaskPullRemoveRepeatPO.getMark();
        if (StringUtils.isBlank(tableName) || (mark == null)) {
            return;
        }
        iSmartCardSyncDataPullDao.updatePullTableStatus(timeTaskPullRemoveRepeatPO);
    }

    /**
     * <desc>
     *     定时任务获取pull表中未处理的数据
     * <desc/>
     *
     * @param smartCardPullPO 查询条件
     * @return List<SmartCardPullPO> 旺龙一卡通需要pull的数据集
     * @author zhangs
     * @createDate 2017/11/3
     */
//    @Override
//    public List<SmartCardPullPO> getUntreatedData(SmartCardPullPO smartCardPullPO) {
//        List<SmartCardPullPO> smartCardPullPOS = new ArrayList<>();
//        //检查合法性
////        String tableName = smartCardPullPO.getTableName();
//        String projectId = smartCardPullPO.getProjectId();
////        String solveMark = smartCardPullPO.getSolveMark();
//        if(StringUtils.isEmpty(tableName) && StringUtils.isBlank(projectId)) {
//            return smartCardPullPOS;
//        }
////        if(!PlatformConstants.MARTCARD_SYNC_DATA_STATUS_YET.equals(solveMark)) {
////            smartCardPullPO.setSolveMark(PlatformConstants.MARTCARD_SYNC_DATA_STATUS_YET);
////        }
//
//        return iSmartCardSyncDataPullDao.getUnhandledData(smartCardPullPO);
//    }

    /**
     * <desc>
     *      根据Id删除对应数据
     * <desc/>
     *
     * @param list 需要删除的pull表的Id
     * @return
     * @author zhangs
     * @createDate 2017/11/3
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer delPullDataByIds(List<Integer> list) {

        return iSmartCardSyncDataPullDao.delPullDataByIds(list);
    }

    /**
     * <desc>
     *      根据Id更新对应数据
     * <desc/>
     *
     * @param tableName  表名称
     * @param smartCardPullPO 与旺龙一卡通对接数据存储实体对象
     * @return
     * @author zhangs
     * @createDate 2017/11/3
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer updatePullDataById(String tableName, SmartCardPullPO smartCardPullPO) {
        this.beforeHandlePullTable(tableName);
        return iSmartCardSyncDataPullDao.updatePullData(tableName, smartCardPullPO);
    }

    /**
     * <desc>
     *      在定时任务临时表中记录有数据变动的pull表
     * <desc/>
     *
     * @param timeTaskPullRemoveRepeatPO 定时任务临时表实体对象
     * @return
     * @author zhangs
     * @createDate 2017/11/3
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void recordPullAtTimeTask(TimeTaskPullRemoveRepeatPO timeTaskPullRemoveRepeatPO) {
        String tableName = timeTaskPullRemoveRepeatPO.getTableName();
        Integer mark = timeTaskPullRemoveRepeatPO.getMark();
        if (StringUtils.isBlank(tableName) || (mark == null)) {
            return;
        }
        Map<String, Object> param = new HashMap<>();
        param.put("tableName", tableName);
        List<TimeTaskPullRemoveRepeatPO> timeTaskPullRemoveRepeatPOS = iSmartCardSyncDataPullDao.obtainPullTableName(param);
        if (timeTaskPullRemoveRepeatPOS.isEmpty()) {
            // 插入
            iSmartCardSyncDataPullDao.savePullTableName(timeTaskPullRemoveRepeatPO);
        } else {
            //更新
            TimeTaskPullRemoveRepeatPO timeTaskPullRemoveRepeat = timeTaskPullRemoveRepeatPOS.get(0);
            timeTaskPullRemoveRepeat.setMark(mark);
            iSmartCardSyncDataPullDao.updatePullTableStatus(timeTaskPullRemoveRepeat);
        }
    }

    /**
     * <desc>
     * 将已处理的云端同步到一卡通的数据进行转移.
     * </desc>
     *
     * @param tableName pull表
     * @return xx
     * @author LewisLouis
     * @createDate 2018-01-09
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void movePullDataToColdTable(String tableName) {
        iSmartCardSyncDataPullDao.movePullDataToColdTable(tableName);

        iSmartCardSyncDataPullDao.removePullData(tableName);
    }

    /**
     * <desc>
     * 获取所有一卡通pul表的信息，用于分析是否需要清理.
     * </desc>
     *
     * @return xx
     * @author LewisLouis
     * @createDate 2018-01-26
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<SmartCardPullTableInfoVO> getAllPullTablesInfo() {
        return iSmartCardSyncDataPullDao.getAllPullTablesInfo();
    }

    /**
    * <desc>
    *     在操作（增、删、改、查记录）pull记录表之前，先进行建表检查.
    * </desc>
    *
    * @param  tableName 表名
    * @author LewisLouis
    * @createDate 2017-12-21
    */
    private void beforeHandlePullTable(String tableName){
        String readisTable = redisService.get(tableName);
        if (StringUtils.isBlank(readisTable)){
            iSmartCardSyncDataPullDao.createPullTable(tableName);
            redisService.set(tableName,tableName);
        };
    }

}
